bitkeeper revision 1.111 (3e6882b5ERWU6qPXXUlLkYvavej4FQ)
authorkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Fri, 7 Mar 2003 11:29:57 +0000 (11:29 +0000)
committerkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Fri, 7 Mar 2003 11:29:57 +0000 (11:29 +0000)
xl_segment.c, xl_scsi.c, xl_ide.c, xl_block.h, xl_block.c:
  Partition tables are now revalidated on demand for all XL blkdevs (IDE, SCSI, and virtual).

xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.h
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c

index 985fda050fdfcd549fff8f5d6d886395e6bf6bc2..567af806b56fd5373053a8067404fa5df57b6fa7 100644 (file)
@@ -34,7 +34,7 @@ static int nr_pending;
 /* Convert from a XenoLinux major device to the Xen-level 'physical' device */
 static inline unsigned short xldev_to_physdev(kdev_t xldev) 
 {
-    unsigned short physdev;
+    unsigned short physdev = 0;
 
     switch ( MAJOR(xldev) ) 
     { 
@@ -49,11 +49,10 @@ static inline unsigned short xldev_to_physdev(kdev_t xldev)
     case XLVIRT_MAJOR:
         physdev = XENDEV_VIRTUAL;
         break;
-
-    default: 
-        BUG();
     } 
 
+    if ( physdev == 0 ) BUG();
+
     physdev += (MINOR(xldev) >> PARTN_SHIFT);
 
     return physdev;
@@ -84,23 +83,36 @@ static inline struct gendisk *xldev_to_gendisk(kdev_t xldev)
     return gd;
 }
 
+
+static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev)
+{
+    struct gendisk *gd = xldev_to_gendisk(xldev);
+    return (xl_disk_t *)gd->real_devices + (MINOR(xldev) >> PARTN_SHIFT);
+}
+
+
 int xenolinux_block_open(struct inode *inode, struct file *filep)
 {
-    DPRINTK("xenolinux_block_open\n"); 
+    xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
+    disk->usage++;
+    DPRINTK("xenolinux_block_open\n");
     return 0;
 }
 
+
 int xenolinux_block_release(struct inode *inode, struct file *filep)
 {
+    xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
+    disk->usage--;
     DPRINTK("xenolinux_block_release\n");
     return 0;
 }
 
 
-
 int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
                          unsigned command, unsigned long argument)
 {
+    kdev_t dev = inode->i_rdev;
     struct hd_geometry *geo = (struct hd_geometry *)argument;
     struct gendisk *gd;     
     struct hd_struct *part; 
@@ -112,10 +124,10 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
     if (!inode)                  return -EINVAL;
 
     DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
-                  command, (long) argument, inode->i_rdev); 
+                  command, (long) argument, dev); 
   
-    gd = xldev_to_gendisk(inode->i_rdev);
-    part = &gd->part[MINOR(inode->i_rdev)]; 
+    gd = xldev_to_gendisk(dev);
+    part = &gd->part[MINOR(dev)]; 
 
     switch ( command )
     {
@@ -125,25 +137,26 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
 
     case BLKRRPART:                               /* re-read partition table */
         DPRINTK_IOCTL("   BLKRRPART: %x\n", BLKRRPART); 
-       break;
+        if ( !capable(CAP_SYS_ADMIN) ) return -EACCES;
+        return xenolinux_block_revalidate(dev);
 
     case BLKSSZGET:
-       switch ( MAJOR(inode->i_rdev) )
+       switch ( MAJOR(dev) )
         {
        case XLIDE_MAJOR: 
            DPRINTK_IOCTL("   BLKSSZGET: %x 0x%x\n", BLKSSZGET, 
-                         xlide_hwsect(MINOR(inode->i_rdev)));
-           return xlide_hwsect(MINOR(inode->i_rdev)); 
+                         xlide_hwsect(MINOR(dev)));
+           return xlide_hwsect(MINOR(dev)); 
 
        case XLSCSI_MAJOR: 
            DPRINTK_IOCTL("   BLKSSZGET: %x 0x%x\n", BLKSSZGET,
-                         xlscsi_hwsect(MINOR(inode->i_rdev)));
-           return xlscsi_hwsect(MINOR(inode->i_rdev)); 
+                         xlscsi_hwsect(MINOR(dev)));
+           return xlscsi_hwsect(MINOR(dev)); 
 
         case XLVIRT_MAJOR:
            DPRINTK_IOCTL("   BLKSSZGET: %x 0x%x\n", BLKSSZGET, 
-                         xlsegment_hwsect(MINOR(inode->i_rdev)));
-           return xlsegment_hwsect(MINOR(inode->i_rdev)); 
+                         xlsegment_hwsect(MINOR(dev)));
+           return xlsegment_hwsect(MINOR(dev)); 
 
        default: 
            printk(KERN_ALERT "BLKSSZGET ioctl() on bogus disk!\n"); 
@@ -202,10 +215,33 @@ int xenolinux_block_check(kdev_t dev)
 
 int xenolinux_block_revalidate(kdev_t dev)
 {
-    DPRINTK("xenolinux_block_revalidate\n"); 
+    struct gendisk *gd = xldev_to_gendisk(dev);
+    xl_disk_t *disk = xldev_to_xldisk(dev);
+    unsigned long flags;
+    int i;
+    
+    spin_lock_irqsave(&io_request_lock, flags);
+    if ( disk->usage > 1 )
+    {
+        spin_unlock_irqrestore(&io_request_lock, flags);
+        return -EBUSY;
+    }
+    spin_unlock_irqrestore(&io_request_lock, flags);
+
+    for ( i = 0; i < (1 << PARTN_SHIFT); i++ )
+    {
+        invalidate_device(dev + i, 1);
+        gd->part[dev + i].start_sect = 0;
+        gd->part[dev + i].nr_sects = 0;
+    }
+
+    grok_partitions(gd, MINOR(dev) >> PARTN_SHIFT,
+                    1 << PARTN_SHIFT, disk->capacity);
+
     return 0;
 }
 
+
 /*
  * hypervisor_request
  *
index 2140b30d7b17690bebe792f66d370e9f1553eff1..17ca09d9f2e6e3f97453a01da6fcf9f26f5fa5b3 100644 (file)
 #define DPRINTK_IOCTL(_f, _a...) ((void)0)
 #endif
 
+/*
+ * We have one of these per XL-IDE, XL-SCSI, and XL-VIRT device.
+ * They hang in an array off the gendisk structure. We may end up putting
+ * all kinds of interesting stuff here :-)
+ */
+typedef struct xl_disk {
+    int usage;
+    unsigned long capacity;
+} xl_disk_t;
+
 /* Generic layer. */
 extern int xenolinux_control_msg(int operration, char *buffer);
 extern int xenolinux_block_open(struct inode *inode, struct file *filep);
index f07c54dcb4a8151df99ae89440957526a57a21d4..9d6ef64c75394228ca263a7c0d17d4e8be9ee6e9 100644 (file)
@@ -78,6 +78,8 @@ int xlide_init(xen_disk_info_t *xdi)
     for ( i = 0; i < xdi->count; i++ )
         if ( xdi->disks[i].type == XEN_DISK_IDE ) units++;
 
+    if ( units == 0 ) return 0;
+
     /* Construct an appropriate gendisk structure. */
     minors    = units * (1<<IDE_PARTN_BITS);
     gd        = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
@@ -88,7 +90,7 @@ int xlide_init(xen_disk_info_t *xdi)
     gd->minor_shift  = IDE_PARTN_BITS; 
     gd->max_p       = 1<<IDE_PARTN_BITS;
     gd->nr_real             = units;           
-    gd->real_devices = NULL;          
+    gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL);
     gd->next        = NULL;            
     gd->fops         = &xlide_block_fops;
     gd->de_arr       = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL);
@@ -97,14 +99,17 @@ int xlide_init(xen_disk_info_t *xdi)
     memset(gd->part,  0, minors * sizeof(struct hd_struct));
     memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units);
     memset(gd->flags, 0, sizeof(*gd->flags) * units);
+    memset(gd->real_devices, 0, sizeof(xl_disk_t) * units);
     xlide_gendisk = gd;
     add_gendisk(gd);
-
+    
     /* Now register each disk in turn. */
     disk = 0;
     for ( i = 0; i < xdi->count; i++ )
     {
         if ( xdi->disks[i].type != XEN_DISK_IDE ) continue;
+        ((xl_disk_t *)gd->real_devices)[disk].capacity =
+            xdi->disks[i].capacity;
         register_disk(gd, 
                       MKDEV(XLIDE_MAJOR, disk<<IDE_PARTN_BITS), 
                       1<<IDE_PARTN_BITS, 
@@ -112,7 +117,7 @@ int xlide_init(xen_disk_info_t *xdi)
                       xdi->disks[i].capacity);
         disk++;
     }
-   
+
     printk(KERN_ALERT 
           "XenoLinux Virtual IDE Device Driver installed [device: %d]\n",
           XLIDE_MAJOR);
index ddbd22d5f16f77d7b26329165386ec90e032241d..68566799bd586b541efd253aa01c7698cba0a9ce 100644 (file)
@@ -79,6 +79,8 @@ int xlscsi_init(xen_disk_info_t *xdi)
     for ( i = 0; i < xdi->count; i++ )
         if ( xdi->disks[i].type == XEN_DISK_SCSI ) units++;
 
+    if ( units == 0 ) return 0;
+
     /* Construct an appropriate gendisk structure. */
     minors    = units * (1<<SCSI_PARTN_BITS);
     gd        = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
@@ -89,7 +91,7 @@ int xlscsi_init(xen_disk_info_t *xdi)
     gd->minor_shift  = SCSI_PARTN_BITS; 
     gd->max_p       = 1<<SCSI_PARTN_BITS;
     gd->nr_real             = units;           
-    gd->real_devices = NULL;          
+    gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL);
     gd->next        = NULL;            
     gd->fops         = &xlscsi_block_fops;
     gd->de_arr       = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL);
@@ -98,6 +100,7 @@ int xlscsi_init(xen_disk_info_t *xdi)
     memset(gd->part,  0, minors * sizeof(struct hd_struct));
     memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units);
     memset(gd->flags, 0, sizeof(*gd->flags) * units);
+    memset(gd->real_devices, 0, sizeof(xl_disk_t) * units);
     xlscsi_gendisk = gd;
     add_gendisk(gd);
 
@@ -106,6 +109,8 @@ int xlscsi_init(xen_disk_info_t *xdi)
     for ( i = 0; i < xdi->count; i++ )
     {
         if ( xdi->disks[i].type != XEN_DISK_SCSI ) continue;
+        ((xl_disk_t *)gd->real_devices)[disk].capacity =
+            xdi->disks[i].capacity;
         register_disk(gd,
                       MKDEV(XLSCSI_MAJOR, disk<<SCSI_PARTN_BITS), 
                       1<<SCSI_PARTN_BITS, 
index 8dfa24fc096a6f53447605f7c7e572df0548acd3..da2086e22c3a116d9480a6efaf6c9e7fc71ca27e 100644 (file)
@@ -96,6 +96,8 @@ int __init xlseg_init(void)
     for ( i = 0; i < xdi->count; i++ )
         if ( xdi->disks[i].type == XEN_DISK_VIRTUAL ) units++;
 
+    if ( units == 0 ) return 0;
+
     /* Construct an appropriate gendisk structure. */
     minors    = units * (1<<VIRT_PARTN_BITS);
     gd        = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
@@ -106,7 +108,7 @@ int __init xlseg_init(void)
     gd->minor_shift  = VIRT_PARTN_BITS; 
     gd->max_p       = 1<<VIRT_PARTN_BITS;
     gd->nr_real             = units;           
-    gd->real_devices = NULL;          
+    gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL);
     gd->next        = NULL;            
     gd->fops         = &xlsegment_block_fops;
     gd->de_arr       = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL);
@@ -115,6 +117,7 @@ int __init xlseg_init(void)
     memset(gd->part,  0, minors * sizeof(struct hd_struct));
     memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units);
     memset(gd->flags, 0, sizeof(*gd->flags) * units);
+    memset(gd->real_devices, 0, sizeof(xl_disk_t) * units);
     xlsegment_gendisk = gd;
     add_gendisk(gd);
 
@@ -123,6 +126,8 @@ int __init xlseg_init(void)
     for ( i = 0; i < xdi->count; i++ )
     {
         if ( xdi->disks[i].type != XEN_DISK_VIRTUAL ) continue;
+        ((xl_disk_t *)gd->real_devices)[disk].capacity =
+            xdi->disks[i].capacity;
         register_disk(gd, 
                       MKDEV(XLVIRT_MAJOR, disk<<VIRT_PARTN_BITS), 
                       1<<VIRT_PARTN_BITS,